﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using Growatt.OSC.Util;
using Oscilloscope.Adjust;
using Oscilloscope.Channel;
using Oscilloscope.ChannelBuffer;
using Oscilloscope.Util;

namespace Oscilloscope.Curve
{
    // Token: 0x0200000A RID: 10
    internal abstract class SingleCurveGenerator : ICurveGenerator, IDisposable
    {
        // Token: 0x06000033 RID: 51 RVA: 0x0000418A File Offset: 0x0000238A
        public SingleCurveGenerator(IChannel channel)
        {
            if (channel == null)
            {
                throw new ArgumentNullException();
            }
            this.channel = channel;
            this.dataBufferIterator = ChannelBufferDataIteratorFactory.ChannelDataBufferIterator(this.channel.GetChannelBuffer().GetSignalType());
        }

        // Token: 0x06000034 RID: 52 RVA: 0x000041C0 File Offset: 0x000023C0
        public CurveVerPosIndicator[] GetCurveVerPosIndicators()
        {
            int height = this.channel.GetCanvasSize().Height;
            float num = (float)height / 2f;
            float yLocInCanvas = (float)((double)num -
                (double)height * (this.channel.GetBaseLineValue()
                / (ValuePerCellAdjustGrade.Instance.GetValueOfGrade(this.channel.GetValuePerCellGrade()) * 8.0)));
            return new CurveVerPosIndicator[]
            {
                new CurveVerPosIndicator(yLocInCanvas, this.channel.GetChannelSN().ToString())
            };
        }

        // Token: 0x06000035 RID: 53 RVA: 0x00004248 File Offset: 0x00002448
        public Curve[] GetCurves()
        {
            var c = new Curve(this.curveSegments, this.curveSegmentCount, this.curvePoints);
            c.curvePointsValues = this.curvePointsValues;
            return new Curve[]
            {
               c
            };
        }
        private double[] curvePointsValues;
        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="dataBuffer"></param>
        /// <param name="dataBufferValidCount"></param>
        /// <param name="dataBufferStartTime"></param>
        /// <summary>
        /// 加载数据并准备曲线
        /// </summary>
        /// <param name="dataBuffer">数据缓冲区</param>
        /// <param name="dataBufferValidCount">有效的数据点数量</param>
        /// <param name="dataBufferStartTime">数据缓冲区开始时间</param>
        public void PrepareCurve(ChannelBufferData[] dataBuffer, int dataBufferValidCount, double dataBufferStartTime)
        {
            // 获取画布大小
            int width = this.channel.GetCanvasSize().Width;
            int height = this.channel.GetCanvasSize().Height;

            // 如果画布宽度或高度小于等于0，则曲线段数量为0，直接返回
            if (width <= 0 || height <= 0)
            {
                this.curveSegmentCount = 0;
                return;
            }

            // 获取时间范围
            double num; // 时间范围的开始
            double num2; // 时间范围的结束
            this.channel.GetTimeSpan(out num, out num2);

            // 计算每个单元格的值范围和时间范围
            double num3 = ValuePerCellAdjustGrade.Instance.GetValueOfGrade(this.channel.GetValuePerCellGrade()) * 8.0;
            float num4 = (float)((double)height * (this.channel.GetChannelBuffer().GetReferenceValue() / num3)); // Y轴参考点的位置
            float num5 = (float)((double)((float)height / 2f) - (double)height * (this.channel.GetBaseLineValue() / num3)); // 基准线的位置
            double num6 = TimePerCellAdjustGrade.Instance.GetValueOfGrade(this.channel.GetTimePerCellGrade()) * 10.0; // 每个单元格的时间范围

            // 初始化数据点和时间变量
            double num7 = 0.0; // 数据点的值
            double num70 = 0.0; // 数据点的值
            double num8 = 0.0; // 数据点的时间
            double num9 = 0.0; // 下一个数据点的值
            double num10 = 0.0; // 下一个数据点的时间

            // 初始化曲线段和点的数量
            int num11 = 0; // 当前曲线段的数量
            this.EnsureCurveBufferCapcity(num11); // 确保曲线段缓冲区有足够的容量
            int num12 = 0; // 当前点的数量
            int num13 = 0; // 已经添加到曲线中的点的总数

            // 用于存储插值点的数组
            PointF[] array = new PointF[2];

            // 清空之前的单个数值列表
            doublesSingle.Clear();

            // 初始化数据缓冲区迭代器
            this.dataBufferIterator.Initialize(dataBuffer, dataBufferValidCount, dataBufferStartTime, this.channel.GetChannelBuffer().GetTimeInterval(), 0);

            var  offset  = this.channel.GetOffset();
            // 遍历数据缓冲区中的每一个数据点
            while (this.dataBufferIterator.Next(ref num7, ref num8))
            {
                // num7 是数据点的值
                // num8 是数据点的时间
                doublesSingle.Add(num7); // 将数据点的值添加到单个数值列表中
                // 计算数据点在画布上的X和Y坐标
                num70 = num7;
                num7 = offset + num7;
                float num14 = (float)((double)width * ((num8 - num) / num6)); // X坐标
                float num15 = (float)((double)num4 - (double)height * (num7 / num3) + (double)num5); // Y坐标

                // 检查数据点是否在画布范围内
                if (num14 >= 0f && num14 <= (float)width && num15 >= 0f && num15 <= (float)height)
                {
                    // 设置新点
                    PointF[] array2 = this.dataBufferIterator.SetNewPoint(num14, num15);
                    if (array2 != null)
                    {
                        foreach (PointF pointF in array2)
                        {
                            // 确保点缓冲区有足够的容量
                            this.EnsurePointBufferCapcity(num13 + num12);

                            // 添加点到曲线点数组中
                            this.curvePoints[num13 + num12] = pointF;

                            // 添加对应的值到曲线点值数组中
                            this.curvePointsValues[num13 + num12] = num70;

                            num12++; // 增加当前点的数量
                        }
                    }
                }
                else
                {
                    // 获取当前点
                    PointF[] point = this.dataBufferIterator.GetPoint();
                    if (point != null)
                    {
                        foreach (PointF pointF2 in point)
                        {
                            // 确保点缓冲区有足够的容量
                            this.EnsurePointBufferCapcity(num13 + num12);

                            // 添加点到曲线点数组中
                            this.curvePoints[num13 + num12] = pointF2;

                            // 添加对应的值到曲线点值数组中
                            this.curvePointsValues[num13 + num12] = num70;

                            num12++; // 增加当前点的数量
                        }
                    }

                    // 如果有有效的点
                    if (num12 > 0)
                    {
                        // 进行插值
                        int num16 = InternalUtils.InterpolationWithCanvas(new PointF(this.curvePoints[num13 + num12 - 1].X, this.curvePoints[num13 + num12 - 1].Y), new PointF(num14, num15), width, height, array);

                        for (int k = 0; k < num16; k++)
                        {
                            // 确保点缓冲区有足够的容量
                            this.EnsurePointBufferCapcity(num13 + num12);

                            // 添加插值点到曲线点数组中
                            this.curvePoints[num13 + num12] = array[k];

                            // 添加对应的值到曲线点值数组中
                            this.curvePointsValues[num13 + num12] = num70;

                            num12++; // 增加当前点的数量
                        }

                        // 设置当前曲线段的起始索引和点的数量
                        this.curveSegments[num11].StartIndex = num13;
                        this.curveSegments[num11].PointCount = num12;

                        num11++; // 增加曲线段的数量
                        this.EnsureCurveBufferCapcity(num11); // 确保曲线段缓冲区有足够的容量

                        num13 += num12; // 增加已经添加到曲线中的点的总数
                        num12 = 0; // 重置当前点的数量
                    }
                    else
                    {
                        // 查看下一个数据点
                        bool flag = this.dataBufferIterator.PeekNext(ref num9, ref num10);
                        if (flag)
                        {
                            // 计算下一个数据点在画布上的X和Y坐标
                            float x = (float)((double)width * ((num10 - num) / num6)); // X坐标
                            float y = (float)((double)num4 - (double)height * (num9 / num3) + (double)num5); // Y坐标

                            // 进行插值
                            int num16 = InternalUtils.InterpolationWithCanvas(new PointF(num14, num15), new PointF(x, y), width, height, array);

                            for (int l = 0; l < num16; l++)
                            {
                                // 确保点缓冲区有足够的容量
                                this.EnsurePointBufferCapcity(num13 + num12);

                                // 添加插值点到曲线点数组中
                                this.curvePoints[num13 + num12] = array[l];

                                // 添加对应的值到曲线点值数组中
                                this.curvePointsValues[num13 + num12] = num70;

                                num12++; // 增加当前点的数量
                            }

                            // 如果有有效的插值点
                            if (num16 > 0)
                            {
                                // 设置当前曲线段的起始索引和点的数量
                                this.curveSegments[num11].StartIndex = num13;
                                this.curveSegments[num11].PointCount = num12;

                                num11++; // 增加曲线段的数量
                                this.EnsureCurveBufferCapcity(num11); // 确保曲线段缓冲区有足够的容量

                                num13 += num12; // 增加已经添加到曲线中的点的总数
                                num12 = 0; // 重置当前点的数量
                            }
                        }
                    }
                }
            }

            // 获取最后一个点
            PointF[] point2 = this.dataBufferIterator.GetPoint();
            if (point2 != null)
            {
                foreach (PointF pointF3 in point2)
                {
                    // 确保点缓冲区有足够的容量
                    this.EnsurePointBufferCapcity(num13 + num12);

                    // 添加点到曲线点数组中
                    this.curvePoints[num13 + num12] = pointF3;

                    // 添加对应的值到曲线点值数组中
                    this.curvePointsValues[num13 + num12] = num70;

                    num12++; // 增加当前点的数量
                }
            }

            // 如果有有效的点
            if (num12 > 0)
            {
                // 设置当前曲线段的起始索引和点的数量
                this.curveSegments[num11].StartIndex = num13;
                this.curveSegments[num11].PointCount = num12;

                num11++; // 增加曲线段的数量
                num13 += num12; // 增加已经添加到曲线中的点的总数
                num12 = 0; // 重置当前点的数量
            }

            // 设置曲线段总数
            this.curveSegmentCount = num11;

            // 记录上一次的曲线段数量
            this.PreviousCurveCount(num11);

            // 记录上一次的点总数
            this.PreviousPointCount(num13 + num12);
        }


        // Token: 0x06000037 RID: 55 RVA: 0x000048D4 File Offset: 0x00002AD4
        protected void EnsureCurveBufferCapcity(int curveIndex)
        {
            if (this.curveSegments == null)
            {
                this.curveSegments = new CurveSegment[SingleCurveGenerator.CURVE_BUFFER_INC_STEP];
            }
            int num = this.curveSegments.Length;
            while (curveIndex >= num)
            {
                num += SingleCurveGenerator.CURVE_BUFFER_INC_STEP;
            }
            if (num != this.curveSegments.Length)
            {
                CurveSegment[] array = this.curveSegments;
                this.curveSegments = new CurveSegment[num];
                Array.Copy(array, this.curveSegments, array.Length);
                this.curveCountLessThanBufferCapcityCount = 0;
            }
        }

        // Token: 0x06000038 RID: 56 RVA: 0x00004944 File Offset: 0x00002B44
        protected void EnsurePointBufferCapcity(int pointIndex)
        {
            if (this.curvePoints == null)
            {
                this.curvePoints = new PointF[SingleCurveGenerator.POINT_BUFFER_INC_STEP];
                this.curvePointsValues = new double[SingleCurveGenerator.POINT_BUFFER_INC_STEP];
            }
            int num = this.curvePoints.Length;
            while (pointIndex >= num)
            {
                num += SingleCurveGenerator.POINT_BUFFER_INC_STEP;
            }
            if (num != this.curvePoints.Length)
            {
                PointF[] array = this.curvePoints;
                this.curvePoints = new PointF[num];
                this.curvePointsValues = new double[num];
                Array.Copy(array, this.curvePoints, array.Length);
                this.pointCountLessThanBufferCapcityCount = 0;
            }
        }

        // Token: 0x06000039 RID: 57 RVA: 0x000049B4 File Offset: 0x00002BB4
        protected void PreviousCurveCount(int previousCurveCount)
        {
            if (this.curveSegments == null)
            {
                return;
            }
            if (this.curveSegments.Length - SingleCurveGenerator.CURVE_BUFFER_DEC_STEP > previousCurveCount)
            {
                this.curveCountLessThanBufferCapcityCount++;
            }
            if (this.curveCountLessThanBufferCapcityCount >= SingleCurveGenerator.BUFFER_SIZE_ADJUST_THRESHOLD)
            {
                CurveSegment[] array = this.curveSegments;
                if (array.Length - SingleCurveGenerator.CURVE_BUFFER_DEC_STEP >= 0)
                {
                    this.curveSegments = new CurveSegment[array.Length - SingleCurveGenerator.CURVE_BUFFER_DEC_STEP];
                    Array.Copy(array, this.curveSegments, array.Length - SingleCurveGenerator.CURVE_BUFFER_DEC_STEP);
                }
                this.curveCountLessThanBufferCapcityCount = 0;
                GC.Collect();
            }
        }

        // Token: 0x0600003A RID: 58 RVA: 0x00004A40 File Offset: 0x00002C40
        protected void PreviousPointCount(int previousPointCount)
        {
            if (this.curvePoints == null)
            {
                return;
            }
            if (this.curvePoints.Length - SingleCurveGenerator.POINT_BUFFER_DEC_STEP > previousPointCount)
            {
                this.pointCountLessThanBufferCapcityCount++;
            }
            if (this.pointCountLessThanBufferCapcityCount >= SingleCurveGenerator.BUFFER_SIZE_ADJUST_THRESHOLD)
            {
                PointF[] array = this.curvePoints;
                this.curvePoints = new PointF[array.Length - SingleCurveGenerator.POINT_BUFFER_DEC_STEP];
                Array.Copy(array, this.curvePoints, array.Length - SingleCurveGenerator.POINT_BUFFER_DEC_STEP);
                this.pointCountLessThanBufferCapcityCount = 0;
                GC.Collect();
            }
        }

        // Token: 0x0600003B RID: 59 RVA: 0x00004ABE File Offset: 0x00002CBE
        public void Dispose()
        {
            this.curveSegments = null;
            this.curvePoints = null;
            this.channel = null;
            GC.Collect();
        }

        // Token: 0x04000014 RID: 20
        private static readonly int CURVE_BUFFER_INC_STEP = 500;

        // Token: 0x04000015 RID: 21
        private static readonly int CURVE_BUFFER_DEC_STEP = 100;

        // Token: 0x04000016 RID: 22
        private static readonly int POINT_BUFFER_INC_STEP = 5000;

        // Token: 0x04000017 RID: 23
        private static readonly int POINT_BUFFER_DEC_STEP = 1000;

        // Token: 0x04000018 RID: 24
        private int pointCountLessThanBufferCapcityCount;

        // Token: 0x04000019 RID: 25
        private int curveCountLessThanBufferCapcityCount;

        // Token: 0x0400001A RID: 26
        private static readonly int BUFFER_SIZE_ADJUST_THRESHOLD = 32;

        // Token: 0x0400001B RID: 27
        private CurveSegment[] curveSegments;

        // Token: 0x0400001C RID: 28
        private int curveSegmentCount;

        // Token: 0x0400001D RID: 29
        private PointF[] curvePoints;

        // Token: 0x0400001E RID: 30
        private IChannel channel;

        // Token: 0x0400001F RID: 31
        private IChannelBufferDataIterator dataBufferIterator;
        List<double> dSingle = new List<double>();
        public List<double> doublesSingle { get => dSingle; }
    }
}
